/*
Copyright (c)2006-2008 - Brett Lajzer

See LICENSE for license information.
*/

#include <lua.h>
#include <lauxlib.h>
#include "globals.h"
#include "funcs_sound.h"
#include "util.h"
#include "hashmap.h"
static const int mix_channels = 16; //the number of mixing channels
static const int mix_rate = 44100; //the mix rate in Hz
static const int mix_format = MIX_DEFAULT_FORMAT; //the output format
static const int mix_op_channels = 2; //output channels, 2 == stereo
static const int mix_chunksize = 256; //output chunk size


// open sound device
void sound_open(){
  //Attempt to open the audio device in this format
  if(Mix_OpenAudio(mix_rate, mix_format, mix_op_channels, mix_chunksize)==-1){
  UTIL_Error("ERROR: Couldn't Initialize SoundEngine: %s", Mix_GetError());
    return;
  }
    
  //Allocate channels
  Mix_AllocateChannels(mix_channels);
    
  //init music to null
  _music = 0;
}
void free_sound_value(void* pv)
{
	Mix_FreeChunk((Mix_Chunk*)pv);
}
// close sound device
void sound_close(){
  //free music if loaded
  if(_music != 0)
    Mix_FreeMusic(_music);
    
  //free up the samples in the sample cache
  hmap_destroy(sample_cache, free_sound_value);
  //for(std::map<std::string, Mix_Chunk*>::iterator it = sample_cache.begin(); it != sample_cache.end(); it++)
  //  Mix_FreeChunk(it->second);    
  //sample_cache.clear();

  Mix_CloseAudio();
}


//play a sample
int l_playsample(lua_State *L){
  Mix_Chunk *s = (Mix_Chunk *)lua_touserdata(L,1);
  
  if(s == NULL){
    return luaL_error(L, "ERROR: Can't play sample, is NULL.");
  }
  
  if(Mix_PlayChannel(-1, s, 0)==-1){
    Mix_AllocateChannels(Mix_AllocateChannels(-1)+1);
    Mix_PlayChannel(-1, s, 0);
  }
  return 0;
}

//stop all samples
int l_stopsamples(lua_State *L){
  Mix_HaltChannel(-1);
  return 0;
}

//load a sample
int l_loadsample(lua_State *L){
  char fullsampleFile[1024];
  const char* soundFile = luaL_checkstring(L,1);
  //Mix_Chunk *temp = 0;
  Mix_Chunk *mixchunk = 0;
  sprintf(fullsampleFile,"%s/%s",gamefullpath,soundFile);
  
  //const char* soundFile = luaL_checkstring(L,1);
  mixchunk = (Mix_Chunk *)hmap_search(sample_cache,fullsampleFile);
  if(!mixchunk)
  {    

    mixchunk = Mix_LoadWAV(fullsampleFile);
    
    if(mixchunk == NULL){
      return luaL_error(L, "ERROR: Can't find sound file: \"%s\".", luaL_checkstring(L,1));
    }
    hmap_insert(sample_cache,soundFile,-1,mixchunk);
    //sample_cache[std::string(luaL_checkstring(L,1))] = temp;
  }

  lua_pushlightuserdata(L,mixchunk);
  return 1;
}

//unload a sample
int l_unloadsample(lua_State *L){
  const char* soundFile = luaL_checkstring(L,1);
  Mix_Chunk *mixchunk = (Mix_Chunk *)hmap_search(sample_cache,soundFile);
  //std::map<std::string, Mix_Chunk *>::iterator s = sample_cache.find(std::string(luaL_checkstring(L,1)));
  if(mixchunk){
    Mix_FreeChunk(mixchunk);
    hmap_insert(sample_cache,soundFile,-1,NULL);
    //sample_cache.erase(s);
  }
  return 0;
}

//clear the sample cache
int l_clearsamples(lua_State *L){
  hmap_destroy(sample_cache, free_sound_value);
  
  return 0;
}


//play music
int l_playmusic(lua_State *L){
  const char* temp = luaL_checkstring(L,1);
  //free up music if not free
  if(_music != 0){
    if(Mix_PlayingMusic())
      Mix_HaltMusic();
    if(strstr(temp ,_music_filename)!=0){ //only free if not loaded
      Mix_FreeMusic(_music);
     }
  }
  if(temp != _music_filename){ //only load if not loaded
    _music = Mix_LoadMUS(temp);
    strcpy(_music_filename ,temp);
  }
    
  //don't halt on error, just output it
  if(!_music)
    return luaL_error(L, "ERROR: Can't load music file \"%s\" : %s.",luaL_checkstring(L,1), Mix_GetError());

  //play the music
  Mix_PlayMusic(_music, lua_tointeger(L,2));
  
  return 0;
}

//stop music
int l_stopmusic(lua_State *L){
  if(_music != 0){
    Mix_HaltMusic();
    Mix_FreeMusic(_music);
    _music_filename = "";
  }
  return 0;
}
